﻿using OnHook.Business.Dto.Common.Setting;
using OnHook.Business.IServices.Common;
using OnHook.Business.Vo.Common;
using OnHook.Common;
using OnHook.Common.Extension;
using OnHook.Domain.Entities;
using OnHook.Framework.Extensions;
using OnHook.Framework.Ioc;
using OnHook.Framework.Pager;
using EasyTool;
using Mapster;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using SqlSugar;

namespace OnHook.Business.Services.Common
{
    /// <summary>
    /// 配置修改服务层
    /// </summary>
    /// <remarks>
    /// 构造函数
    /// </remarks>
    public class SettingService(IConfiguration configuration, ISqlSugarClient db, IHostEnvironment enviroment) : ISettingService, IScoped
    {
        /// <summary>
        /// 配置
        /// </summary>
        protected readonly IConfiguration _configuration = configuration;
        /// <summary>
        /// 数据库
        /// </summary>
        protected readonly ISqlSugarClient _db = db;
        /// <summary>
        /// 环境
        /// </summary>
        private string _env = enviroment.EnvironmentName.ToLower();

        /// <summary>
        /// 查询配置列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<SettingVo>> GetSettingsAsync()
        {
            return (await _db.Queryable<Setting>().Where(c => c.Env == _env).ToListAsync()).Adapt<List<SettingVo>>();
        }
        /// <summary>
        /// 根据Key查询配置
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<SettingVo> GetSettingByKeyAsync(string key)
        {
            var entity = await _db.Queryable<Setting>().FirstAsync(c => c.Key == key && c.Env == _env);
            return entity.Adapt<SettingVo>();
        }

        /// <summary>
        ///  分页查询系统配置
        /// </summary>
        /// <param name="searchDto"></param>
        /// <returns></returns>
        public async Task<PagedList<Setting>> GetSettingPagerAsync(SettingPageSearchDto searchDto)
        {
            var query = _db.Queryable<Setting>(); //_repository.GetDbClient().Queryable<Setting>();
            if (searchDto.IsNotNull())
            {
                if (StrUtil.IsNullOrEmpty(searchDto.Keyword))
                {
                    query = query.Where(c => c.Key.Contains(searchDto.Keyword) || c.Value.Contains(searchDto.Keyword));
                }

                if (StrUtil.IsNullOrEmpty(searchDto.Env))
                {
                    searchDto.Env = "dev";
                }
            }
            else
            {
                searchDto = new SettingPageSearchDto() { Env = "development" };
            }
            query = query.Where(c => c.Env == searchDto.Env);

            RefAsync<int> count = 0;
            var result = await query.ToPageListAsync(searchDto.PageIndex, searchDto.PageSize, count);
            var pagedList = searchDto.ToPagedList(result, count);
            return pagedList;
        }

        /// <summary>
        /// 根据Key获取value值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public async Task<string> GetSettingValueAsync(string key, string defaultValue = "")
        {
            string value;
            var dto = await GetSettingByKeyAsync(key);
            if (dto.IsNotNull())
            {
                value = dto.Value;
            }
            else
            {
                value = defaultValue;
            }
            return value;
        }
        /// <summary>
        /// 根据optionKey获取配置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="optionKey"></param>
        /// <returns></returns>
        public async Task<T> GetSettingOptionAsync<T>(string optionKey)
        {
            var settingList = await _db.Queryable<Setting>().Where(x => x.OptionKey == optionKey).ToListAsync();

            var type = typeof(T);
            var properties = type.GetProperties();
            var obj = ReflectUtil.CreateInstance(type);
            foreach (var item in settingList)
            {
                var property = properties.FirstOrDefault(x => string.Compare(item.Key, x.Name, StringComparison.OrdinalIgnoreCase) == 0);
                if (property != null && property.SetMethod != null)
                {
                    object? objValue = item.Value.ChangeType(property.PropertyType);
                    property.SetValue(obj, objValue);
                }
            }
            return (T)obj;
        }

    }
}
